﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace AgLux
{
    /// <summary>
    /// Represents a canvas that displays a course section.
    /// </summary>

    public class Section : Canvas
    {
        public event EventHandler HeightChanged;
        public event EventHandler FullScreenEntered;
        public event EventHandler FullScreenLeft;

        private string _headline;
        private List<Component> _components;
        private List<Section> _sections;

        /// <summary>
        /// Initializes a new instance of the Section class.
        /// </summary>

        /// <param name="headline">
        /// The section headline.
        /// </param>

        /// <param name="components">
        /// The list of Component objects.
        /// </param>

        /// <param name="sections">
        /// The list of Section objects.
        /// </param>

        public Section(string headline, List<Component> components, List<Section> sections)
            : base()
        {
            _headline = headline;
            _components = components;
            _sections = sections;

            foreach (Component component in components)
            {
                component.HeightChanged += new EventHandler(AdjustHeight);
                component.FullScreenLeft += new EventHandler(LeaveFullScreen);
                component.FullScreenEntered += new EventHandler(EnterFullScreen);
                Children.Add(component);
            }
        }

        /// <summary>
        /// Gets the section headline.
        /// </summary>

        public string Headline
        {
            get
            {
                return _headline;
            }
        }

        /// <summary>
        /// Gets the subsections.
        /// </summary>

        public List<Section> Sections
        {
            get
            {
                return _sections;
            }
        }

        /// <summary>
        /// Gets the section content as HTML.
        /// </summary>

        public string Html
        {
            get
            {
                string html = "";

                foreach (Component component in _components)
                {
                    if (component.GetType().ToString() == "AgLux.Text")
                    {
                        Text text = (Text)component;
                        html += "<br/><br/>" + text.Html;
                    }

                    else if (component.GetType().ToString() == "AgLux.Picture")
                    {
                        Picture picture = (Picture)component;
                        html += "<br/><br/>" + picture.Html;
                    }
                }

                return html;
            }
        }

        /// <summary>
        /// Gets the section content.
        /// </summary>

        /// <param name="sequence">
        /// The section number sequence.
        /// </param>

        /// <param name="includingComponents">
        /// Whether the section components should be included.
        /// </param>

        /// <returns>
        /// The section content.
        /// </returns>

        public string PrintContent(List<int> sequence, bool includeComponents)
        {
            string content = "";

            foreach (int number in sequence)
            {
                content += number + 1 + ".";
            }

            content += " " + _headline + "\n";

            if (includeComponents)
            {
                foreach (Component component in _components)
                {
                    content += "   " + component.ToString() + "\n";
                }
            }

            content += "\n";
            sequence.Add(0);

            foreach (Section section in _sections)
            {
                content += section.PrintContent(sequence, includeComponents);
                sequence[sequence.Count - 1]++;
            }

            sequence.RemoveAt(sequence.Count - 1);
            return content;
        }

        /// <summary>
        /// Prepare to display the section.
        /// </summary>

        /// <param name="width">
        /// The width of the canvas on which the section will be displayed.
        /// </param>

        public void Prepare(double width)
        {
            Width = width;

            foreach (Component component in _components)
            {
                component.Prepare(width);
            }
        }

        /// <summary>
        /// Ends the activity of the section.
        /// </summary>

        public void End()
        {
            foreach (Component component in _components)
            {
                component.End();
            }
        }

        /// <summary>
        /// Occurs when the height of a component is changed.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void AdjustHeight(object sender, EventArgs args)
        {
            Height = 20;

            foreach (Component component in _components)
            {
                component.SetValue(Canvas.TopProperty, Height);

                if (component.Height > 0)
                {
                    Height += component.Height + 20;
                }
            }

            OnHeightChanged(new EventArgs());
        }

        /// <summary>
        /// Occurs when a component enters full screen.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void EnterFullScreen(object sender, EventArgs args)
        {
            Component fullScreenComponent = (Component)sender;
            SetValue(Canvas.LeftProperty, -(double)fullScreenComponent.GetValue(Canvas.LeftProperty));
            SetValue(Canvas.TopProperty, -(double)fullScreenComponent.GetValue(Canvas.TopProperty));

            foreach (Component component in _components)
            {
                component.Visibility = Visibility.Collapsed;
            }

            fullScreenComponent.Visibility = Visibility.Visible;
            OnFullScreenEntered(new EventArgs());
        }

        /// <summary>
        /// Occurs when a component leaves full screen.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void LeaveFullScreen(object sender, EventArgs args)
        {
            foreach (Component component in _components)
            {
                component.Visibility = Visibility.Visible;
            }

            OnFullScreenLeft(new EventArgs());
        }

        /// <summary>
        /// Raises the HeightChanged event.
        /// </summary>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void OnHeightChanged(EventArgs args)
        {
            if (HeightChanged != null)
            {
                HeightChanged(this, args);
            }
        }

        /// <summary>
        /// Raises the FullScreenEntered event.
        /// </summary>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void OnFullScreenEntered(EventArgs args)
        {
            if (FullScreenEntered != null)
            {
                FullScreenEntered(this, args);
            }
        }

        /// <summary>
        /// Raises the FullScreenLeft event.
        /// </summary>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void OnFullScreenLeft(EventArgs args)
        {
            if (FullScreenLeft != null)
            {
                FullScreenLeft(this, args);
            }
        }
    }
}
